import pandas as pd
import numpy as np
import json
import logging
import matplotlib.pyplot as plt
from datetime import datetime
import openai
from sklearn.feature_extraction.text import TfidfVectorizer
import os
import re
import traceback

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class SkillDiagnosisSystem:
    """能力诊断系统"""
    
    def __init__(self, config):
        self.config = config
        openai.api_key = self.config["openai_api_key"]
        openai.base_url = self.config.get("openai_base_url", "https://api.openai.com/v1/")
        
    def analyze_resume(self, resume_text):
        """分析简历并提取技能
        
        Args:
            resume_text (str): 简历文本内容
            
        Returns:
            dict: 提取的技能和技能水平
        """
        try:
            # 使用更明确的提示改进技能提取
            prompt = f"""
            请仔细分析以下简历文本，提取所有专业技能及其熟练程度。
            
            对于技能水平评估，请使用以下标准：
            - 精通/专业/精通/专精 = 90-95分
            - 熟练/扎实/过硬/资深 = 80-89分
            - 熟悉/掌握/有经验 = 70-79分
            - 了解/入门/使用过 = 60-69分
            - 简历中未提及但相关工作经验表明可能具备的技能 = 50-59分
            
            简历文本：
            ---
            {resume_text}
            ---
            
            请注意：即使简历中没有明确描述某技能的水平，也请根据工作经验、项目描述和上下文评估水平。不要将任何技能水平设为0或低于50分。
            
            请返回JSON格式的结果，包含`skills`对象，记录技能名称和对应评分(0-100)：
            {{
                "skills": {{
                    "技能名称1": 评分,
                    "技能名称2": 评分,
                    ...
                }}
            }}
            """
            
            response = openai.chat.completions.create(
                model=self.config["llm_model"],
                messages=[
                    {"role": "system", "content": "你是一位专业的简历分析专家，擅长从简历中提取技能信息并评估技能水平。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.3,
                response_format={"type": "json_object"}
            )
            
            # 捕获并记录API返回的原始内容用于调试
            content = response.choices[0].message.content
            logger.debug(f"API返回的技能数据: {content}")
            
            # 解析返回的JSON
            try:
                skills_data = json.loads(content)
            except json.JSONDecodeError as e:
                logger.error(f"JSON解析错误: {str(e)}, 原始内容: {content}")
                # 尝试修复常见的JSON格式问题
                fixed_content = content.replace("'", '"').strip()
                try:
                    skills_data = json.loads(fixed_content)
                except:
                    # 如果仍然失败，使用备用方法
                    logger.warning("无法解析API返回的JSON，使用备用技能提取方法")
                    return {"skills": self._extract_basic_skills_enhanced(resume_text)}
            
            # 验证并修复结果格式
            if not isinstance(skills_data, dict):
                logger.warning(f"API返回的不是字典: {type(skills_data)}")
                return {"skills": self._extract_basic_skills_enhanced(resume_text)}
            
            if 'skills' not in skills_data or not skills_data['skills']:
                logger.warning("API返回的数据中没有'skills'字段或为空")
                return {"skills": self._extract_basic_skills_enhanced(resume_text)}
            
            # 确保skills是字典类型
            if not isinstance(skills_data['skills'], dict):
                logger.warning(f"API返回的'skills'不是字典: {type(skills_data['skills'])}")
                return {"skills": self._extract_basic_skills_enhanced(resume_text)}
            
            # 确保技能值为数值类型，但不设置下限
            for skill, level in skills_data['skills'].items():
                if not isinstance(level, (int, float)):
                    skills_data['skills'][skill] = 0  # 如果不是数值类型，设为0
            
            return skills_data
            
        except Exception as e:
            logger.error(f"简历分析错误: {str(e)}")
            # 使用备用方法
            return {"skills": self._extract_basic_skills_enhanced(resume_text)}
        
    def _extract_basic_skills_enhanced(self, resume_text):
        """增强版从简历文本中提取基本技能
        
        Args:
            resume_text (str): 简历文本
            
        Returns:
            dict: 提取的技能和估计水平
        """
        # 扩展技能关键词词典，包含中英文技能名称 - 保留原有基础分数，但允许系统设置为0分
        skill_keywords = {
            # 编程语言
            'python': 75, 'java': 70, 'c++': 70, 'javascript': 70, 'typescript': 70,
            'c#': 70, 'go': 75, 'php': 70, 'ruby': 70, 'swift': 70, 'r语言': 70, 'r': 70,
            
            # 数据相关
            'sql': 70, 'mysql': 70, 'postgresql': 70, 'mongodb': 70, 'redis': 70,
            'oracle': 75, 'sqlite': 65, '数据库': 70, '数据仓库': 75, 
            '数据建模': 75, '数据挖掘': 75, '数据分析': 75, '数据可视化': 70,
            
            # 数据科学/AI
            'pandas': 75, 'numpy': 75, 'scipy': 70, 'matplotlib': 70, 'scikit-learn': 70,
            'sklearn': 70, 'pytorch': 75, 'tensorflow': 75, '机器学习': 75, 'excel': 65,
            '深度学习': 80, '神经网络': 75, 'nlp': 75, '自然语言处理': 75,
            '计算机视觉': 75, 'cv': 75, '强化学习': 80, '推荐系统': 75,
            
            # 大数据
            'hadoop': 75, 'spark': 75, 'hive': 70, 'flink': 75, 'kafka': 70,
            
            # Web开发
            'html': 65, 'css': 65, 'react': 70, 'vue': 70, 'angular': 70,
            'django': 70, 'flask': 70, 'spring': 70, 'bootstrap': 65,
            
            # 工具和平台
            'git': 65, 'docker': 70, 'kubernetes': 75, 'linux': 65, 'aws': 70, 
            'azure': 70, '阿里云': 70, '腾讯云': 70, 'tableau': 70, 'power bi': 70,
            
            # 软技能
            '沟通能力': 70, '团队协作': 70, '项目管理': 70, '解决问题': 70
        }
        
        # 转为小写以进行不区分大小写的匹配
        resume_lower = resume_text.lower()
        
        # 提取找到的技能
        found_skills = {}
        
        for skill, base_score in skill_keywords.items():
            if skill in resume_lower:
                # 技能出现在简历中，默认评分为基础分数
                found_skills[skill.title()] = base_score
        
        # 如果没有找到任何技能，可以返回空字典而不是默认技能
        if not found_skills:
            # 可以选择返回空字典
            return {}
            # 或者保留原有逻辑，但使用更低的默认分数
            # 根据简历中可能包含的关键词推断基本技能
            if '数据' in resume_lower or '分析' in resume_lower:
                return {'Python': 65, 'SQL': 70, '数据分析': 75, '数据可视化': 65}
            elif '开发' in resume_lower or '编程' in resume_lower:
                return {'Python': 70, 'Java': 65, 'JavaScript': 65, 'Git': 60}
            elif '设计' in resume_lower:
                return {'UI设计': 70, 'Photoshop': 65, '用户体验': 70}
            elif '产品' in resume_lower:
                return {'产品管理': 70, '需求分析': 65, '用户研究': 60}
            elif '市场' in resume_lower or '营销' in resume_lower:
                return {'市场分析': 70, '营销策略': 65, '社交媒体': 70}
            else:
                return {'办公软件': 70, '沟通能力': 65, '团队协作': 70}
        
        return found_skills
    
    def analyze_job(self, job_description):
        """分析职位描述，提取所需技能和要求水平
        
        Args:
            job_description (str): 职位描述文本
            
        Returns:
            tuple: (技能要求字典, 保存的JSON文件路径)
        """
        logger.info("开始分析职位描述...")
        
        try:
            # 构建提示
            prompt = f"""
            请分析以下职位描述，提取所需技能并评估要求水平（0-100分）：

            {job_description}

            请以JSON格式返回，包含以下内容：
            1. skills: 字典格式，键为技能名称，值为要求水平评分(0-100)
            2. experience: 要求工作经验（年）
            3. education: 学历要求
            4. job_type: 工作类型（全职/兼职/实习等）
            5. key_responsibilities: 主要职责（列表）
            6. must_have_skills: 必备技能（列表）
            7. nice_to_have_skills: 加分技能（列表）

            在评估要求水平时，请注意：
            - 50分表示一般要求，75分表示较高要求，90+分表示专家级要求
            - 必备技能分数通常更高，加分技能可以相对较低
            - 所有技能至少应有40分以上（表示确实需要此技能）
            
            请确保每个技能都有一个明确的评分，不要出现0分的技能。
            """
            
            # 调用GPT API
            response = openai.chat.completions.create(
                model=self.config["llm_model"],
                messages=[
                    {"role": "system", "content": "你是一位专业的招聘顾问，擅长分析职位描述和提取技能要求。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.5,
                response_format={"type": "json_object"}
            )
            
            # 解析返回的JSON
            job_analysis = json.loads(response.choices[0].message.content)
            
            # 确保skills字典存在且有值
            if 'skills' not in job_analysis or not job_analysis['skills']:
                logger.warning("未从API返回中检测到技能信息，将使用默认值")
                job_analysis['skills'] = {"基础技能": 40}
            
            # 确保没有非数值的技能
            for skill, level in list(job_analysis['skills'].items()):
                if not isinstance(level, (int, float)):
                    job_analysis['skills'][skill] = 0  # 如果不是数值类型，设为0
            
            # 保存结果
            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
            filename = f"data/job_skills_{timestamp}.json"
            
            # 确保目录存在
            os.makedirs("data", exist_ok=True)
            
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(job_analysis, f, ensure_ascii=False, indent=2)
            
            logger.info(f"从职位描述中提取到 {len(job_analysis.get('skills', {}))} 项所需技能")
            
            return job_analysis, filename
            
        except Exception as e:
            logger.error(f"分析职位描述出错: {str(e)}")
            return None, None
    
    def analyze_job_requirements(self, job_description):
        """分析职位要求，提取所需技能
        
        Args:
            job_description (str): 职位描述
            
        Returns:
            dict: 提取的职位所需技能及重要性评分
        """
        try:
            # 使用LLM提取技能需求
            skills = self._extract_skills_from_job(job_description)
            logger.info(f"从职位描述中提取到 {len(skills)} 项所需技能")
            return skills
        except Exception as e:
            logger.error(f"职位分析错误: {str(e)}")
            return {}
    
    def _extract_skills_from_job(self, job_description):
        """使用LLM从职位描述中提取技能需求"""
        try:
            response = openai.chat.completions.create(
                model=self.config["llm_model"],
                messages=[
                    {"role": "system", "content": "你是一位人才招聘专家，请从职位描述中提取关键技能需求并评估重要性。"},
                    {"role": "user", "content": f"请从以下职位描述中提取所有技能需求，并评估重要性(1-100分)，以JSON格式返回，例如{{\"Python\": 90, \"数据分析\": 80}}:\n\n{job_description}"}
                ],
                temperature=0.3,
                response_format={"type": "json_object"}
            )
            
            result = response.choices[0].message.content
            skills_json = json.loads(result)
            
            if "required_skills" in skills_json:
                return skills_json["required_skills"]
            return json.loads(result)  # 直接返回整个JSON对象
            
        except Exception as e:
            logger.error(f"职位技能提取错误: {str(e)}")
            return {}
    
    def generate_skill_gap_analysis(self, user_skills, job_skills):
        """生成技能差距分析
        
        Args:
            user_skills (dict): 用户技能及评分
            job_skills (dict): 职位所需技能及重要性评分
            
        Returns:
            dict: 技能差距分析结果
        """
        # 初始化结果字典
        gap_analysis = {
            'matching_score': 0,  # 总体匹配度
            'skill_gaps': {},     # 技能差距详情
            'strengths': {},      # 优势技能
            'missing_skills': [], # 缺失技能
            'recommendations': [], # 提升建议
            'overall_match_percentage': 0  # 增加总体匹配度百分比字段
        }
        
        # 如果没有提取到技能，返回空结果
        if not user_skills or not job_skills:
            return gap_analysis
            
        # 计算技能差距
        all_skills = set(list(user_skills.keys()) + list(job_skills.keys()))
        
        total_weighted_score = 0
        total_weights = 0
        
        for skill in all_skills:
            job_importance = job_skills.get(skill, 0)
            user_level = user_skills.get(skill, 0)
            
            # 只考虑职位要求的技能
            if job_importance > 0:
                # 计算差距
                gap = user_level - job_importance
                
                # 加权计算总体匹配度
                normalized_score = min(100, max(0, user_level)) / 100.0
                weighted_score = normalized_score * job_importance
                total_weighted_score += weighted_score
                total_weights += job_importance
                
                # 计算匹配度百分比
                match_percentage = (user_level / job_importance * 100) if job_importance > 0 else 0
                match_percentage = min(100, max(0, match_percentage))  # 限制在0-100范围内
                
                # 记录技能差距
                if gap < 0:
                    # 技能不足
                    gap_analysis['skill_gaps'][skill] = {
                        'user_level': user_level,
                        'required_level': job_importance,
                        'gap': gap,
                        'improvement_needed': abs(gap),
                        'match_percentage': match_percentage  # 添加匹配度百分比
                    }
                elif gap >= 10:
                    # 技能优势（超出10分以上）
                    gap_analysis['strengths'][skill] = {
                        'user_level': user_level,
                        'required_level': job_importance,
                        'advantage': gap,
                        'match_percentage': 100  # 优势技能匹配度为100%
                    }
                    
            # 记录缺失的技能
            if job_importance > 40 and skill not in user_skills:
                gap_analysis['missing_skills'].append({
                    'skill': skill,
                    'importance': job_importance,
                    'match_percentage': 0  # 缺失技能匹配度为0%
                })
                
        # 计算总体匹配度（0-100）
        if total_weights > 0:
            gap_analysis['matching_score'] = int((total_weighted_score / total_weights) * 100)
            gap_analysis['overall_match_percentage'] = gap_analysis['matching_score']
        
        # 生成提升建议
        recommendations = self._generate_improvement_recommendations(
            gap_analysis['skill_gaps'],
            gap_analysis['missing_skills']
        )
        gap_analysis['recommendations'] = recommendations
        
        return gap_analysis
    
    def _generate_improvement_recommendations(self, skill_gaps, missing_skills):
        """生成技能提升建议"""
        recommendations = []
        
        # 按改进需求程度排序技能差距
        sorted_gaps = sorted(
            skill_gaps.items(), 
            key=lambda x: x[1]['improvement_needed'], 
            reverse=True
        )
        
        # 针对最大的3个差距提出建议
        priority_gaps = sorted_gaps[:3]
        for skill, data in priority_gaps:
            improvement = data['improvement_needed']
            recommendations.append({
                'skill': skill,
                'current_level': data['user_level'],
                'target_level': data['required_level'],
                'priority': 'high' if improvement > 30 else 'medium',
                'suggestion': f"将{skill}技能从{data['user_level']}分提升至{data['required_level']}分"
            })
            
        # 针对缺失技能提出建议
        for missing in missing_skills:
            skill = missing['skill']
            importance = missing['importance']
            
            recommendations.append({
                'skill': skill,
                'current_level': 0,
                'target_level': importance,
                'priority': 'critical',
                'suggestion': f"学习{skill}技能，达到{importance}分水平"
            })
            
        return recommendations
        
    def generate_radar_chart(self, user_skills, job_skills, output_path=None):
        """生成技能雷达图
        
        Args:
            user_skills (dict): 用户技能及评分
            job_skills (dict): 职位所需技能及重要性评分
            output_path (str, optional): 输出图片路径
            
        Returns:
            str: 图片保存路径或None
        """
        try:
            # 合并两组技能，只保留共有的和职位要求的关键技能
            common_skills = {}
            
            for skill, importance in job_skills.items():
                if importance >= 50:  # 只考虑重要性大于50的技能
                    common_skills[skill] = {
                        'job': importance,
                        'user': user_skills.get(skill, 0)
                    }
                    
            # 如果技能太多，只保留前8个最重要的
            if len(common_skills) > 8:
                common_skills = dict(sorted(
                    common_skills.items(), 
                    key=lambda x: x[1]['job'], 
                    reverse=True
                )[:8])
                
            if not common_skills:
                logger.warning("没有足够的共同技能生成雷达图")
                return None
                
            # 准备绘图数据
            categories = list(common_skills.keys())
            job_values = [common_skills[skill]['job'] for skill in categories]
            user_values = [common_skills[skill]['user'] for skill in categories]
            
            # 设置图表
            fig = plt.figure(figsize=(10, 8))
            ax = fig.add_subplot(111, polar=True)
            
            # 计算角度
            N = len(categories)
            angles = [n / float(N) * 2 * np.pi for n in range(N)]
            angles += angles[:1]  # 闭合雷达图
            
            # 添加用户技能线
            user_values += user_values[:1]
            ax.plot(angles, user_values, 'o-', linewidth=2, label='您的技能水平')
            ax.fill(angles, user_values, alpha=0.25)
            
            # 添加职位需求线
            job_values += job_values[:1]
            ax.plot(angles, job_values, 'o-', linewidth=2, label='职位要求水平')
            ax.fill(angles, job_values, alpha=0.1)
            
            # 添加分类标签
            plt.xticks(angles[:-1], categories, fontsize=12)
            
            # 添加图例和标题
            plt.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))
            plt.title('技能差距分析雷达图', size=15)
            
            # 保存图表
            if output_path:
                plt.savefig(output_path, dpi=300, bbox_inches='tight')
                logger.info(f"雷达图已保存至 {output_path}")
                plt.close()
                return output_path
            else:
                # 生成临时文件路径
                timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
                output_path = f"data/skill_radar_{timestamp}.png"
                plt.savefig(output_path, dpi=300, bbox_inches='tight')
                plt.close()
                return output_path
                
        except Exception as e:
            logger.error(f"雷达图生成错误: {str(e)}")
            return None

    def visualize_skill_gap(self, user_skills, job_skills, output_path=None):
        """可视化技能差距
        
        Args:
            user_skills (dict): 用户技能
            job_skills (dict): 职位要求技能
            output_path (str, optional): 输出文件路径
            
        Returns:
            str: 图表保存路径
        """
        try:
            # 设置中文字体
            plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial Unicode MS', 'DejaVu Sans']
            plt.rcParams['axes.unicode_minus'] = False
            
            # 提取共同技能
            common_skills = set(user_skills.keys()) & set(job_skills.keys())
            
            # 如果没有共同技能，加入所有技能
            if not common_skills:
                common_skills = set(user_skills.keys()) | set(job_skills.keys())
            
            # 限制技能数量，避免图表过于拥挤
            if len(common_skills) > 8:
                # 基于职位要求水平选择最重要的技能
                sorted_skills = sorted(common_skills, key=lambda x: job_skills.get(x, 0), reverse=True)
                common_skills = set(sorted_skills[:8])
            
            # 整理数据
            skills = list(common_skills)
            user_values = [user_skills.get(skill, 0) for skill in skills]
            job_values = [job_skills.get(skill, 0) for skill in skills]
            
            # 计算角度
            angles = np.linspace(0, 2*np.pi, len(skills), endpoint=False).tolist()
            
            # 闭合图形
            skills.append(skills[0])
            user_values.append(user_values[0])
            job_values.append(job_values[0])
            angles.append(angles[0])
            
            # 关键修改：创建极坐标图
            fig, ax = plt.subplots(figsize=(8, 6), subplot_kw={'projection': 'polar'})
            
            # 绘制网格
            ax.plot(angles, job_values, 'o-', linewidth=2, label='职位要求', color='#3498db')
            ax.fill(angles, job_values, alpha=0.1, color='#3498db')
            
            ax.plot(angles, user_values, 'o-', linewidth=2, label='您的水平', color='#e74c3c')
            ax.fill(angles, user_values, alpha=0.1, color='#e74c3c')
            
            # 设置标签
            ax.set_thetagrids(np.degrees(angles[:-1]), skills[:-1])
            
            # 设置y轴范围
            ax.set_ylim(0, 100)
            
            # 添加图例
            ax.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))
            
            # 标题
            plt.title('技能匹配度分析', fontsize=14, pad=20)
            
            # 保存图表
            if not output_path:
                timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
                output_path = f"data/skill_gap_{timestamp}.png"
            
            # 确保目录存在
            os.makedirs(os.path.dirname(output_path), exist_ok=True)
            
            plt.savefig(output_path, dpi=150, bbox_inches='tight')
            plt.close(fig)
            
            return output_path
            
        except Exception as e:
            logger.error(f"技能差距可视化错误: {str(e)}")
            return None

    def analyze_resume_and_job_together(self, resume_text, job_description):
        """同时分析简历和职位描述，确保技能名称一致性
        
        Args:
            resume_text (str): 简历文本内容
            job_description (str): 职位描述文本
            
        Returns:
            tuple: (用户技能字典, 职位技能字典, 匹配分析)
        """
        try:
            prompt = f"""
            请同时分析以下简历和职位描述，提取匹配的技能信息：
            
            【简历内容】
            {resume_text}
            
            【职位描述】
            {job_description}
            
            请完成以下任务：
            1. 从职位描述中提取所有要求的技能，并评估重要程度（0-100分）
            2. 从简历中评估候选人对每项技能的掌握水平（0-100分）
            3. 确保从简历和职位描述中提取的技能名称保持一致
            4. 如果简历中没有明确提到某项职位要求的技能，可以设置为0分或根据相关经验推断一个合理值
            5. 计算每项技能的匹配度百分比（候选人水平/职位要求*100%，职位要求为0时匹配度为0%）
            6. 计算总体匹配度（按职位要求重要性加权平均）
            7. 评估候选人的就业竞争力
            8. 提供3-5条具体的提升建议
            9. 分析该职位的行业发展前景
            
            请以JSON格式返回，结构如下：
            {{
                "job_skills": {{
                    "技能1": 重要程度,
                    "技能2": 重要程度,
                    ...
                }},
                "user_skills": {{
                    "技能1": 掌握水平,
                    "技能2": 掌握水平,
                    ...
                }},
                "match_analysis": {{
                    "技能1": {{
                        "job_requirement": 重要程度,
                        "user_level": 掌握水平,
                        "match_percentage": 匹配百分比,
                        "gap": 差距
                    }},
                    "技能2": {{...}},
                    ...
                }},
                "overall_match": 总体匹配度百分比,
                "competitiveness_analysis": "对候选人就业竞争力的评价",
                "improvement_suggestions": [
                    "提升建议1",
                    "提升建议2",
                    "提升建议3"
                ],
                "career_prospects": "职位发展前景分析"
            }}
            
            注意：
            - 对于职位要求中提到但简历中没有的技能，根据简历中的相关经验评估一个合理的水平，最低不低于40分
            - 匹配百分比 = min(100%, 用户水平/职位要求*100%)
            - 总体匹配度为所有技能匹配度的加权平均（按职位要求重要性加权）
            - 提升建议应该针对技能差距最大的领域，并提供具体学习路径
            - 职位发展前景应考虑当前市场需求和行业趋势
            """
            
            response = openai.chat.completions.create(
                model=self.config["llm_model"],
                messages=[
                    {"role": "system", "content": "你是一位专业的人才匹配专家，擅长分析简历和职位描述，评估技能匹配度。"},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.3,
                response_format={"type": "json_object"}
            )
            
            # 获取API响应内容后添加更严格的类型检查和错误处理
            content = response.choices[0].message.content
            logger.info(f"API返回的原始数据类型: {type(content)}")
            
            # 添加详细日志以排查问题
            if isinstance(content, str):
                logger.info(f"API返回的前100个字符: {content[:100]}")
            
            # 检查返回内容是否为空
            if not content or not content.strip():
                logger.error("API返回的内容为空")
                return {}, {}, {}
            
            # 尝试解析JSON，添加更多错误处理
            try:
                # 确保content是字符串
                if not isinstance(content, str):
                    content = str(content)
                    
                # 解析JSON
                result = json.loads(content)
                
                # 验证结果是否为字典
                if not isinstance(result, dict):
                    logger.error(f"API返回的不是有效的JSON对象，而是: {type(result)}")
                    # 尝试修复非字典结果
                    if isinstance(result, str):
                        try:
                            # 再次尝试解析，可能是嵌套的JSON字符串
                            result = json.loads(result) 
                        except:
                            result = {}
                    else:
                        result = {}
                    
                # 验证关键字段
                for key in ['user_skills', 'job_skills', 'match_analysis', 'overall_match']:
                    # 确保每个字段都存在且为正确类型
                    if key not in result:
                        result[key] = {} if key != 'overall_match' else 0
                    elif key in ['user_skills', 'job_skills', 'match_analysis']:
                        if not isinstance(result[key], dict):
                            logger.error(f"{key}不是字典类型: {type(result[key])}")
                            result[key] = {}
                    elif key == 'overall_match':
                        if not isinstance(result[key], (int, float)):
                            try:
                                result[key] = float(result[key])
                            except:
                                result[key] = 0
                
                # 确保match_analysis中的每个项目也是字典
                for skill, data in list(result.get('match_analysis', {}).items()):
                    if not isinstance(data, dict):
                        logger.error(f"技能{skill}的匹配分析不是字典: {type(data)}")
                        # 移除不是字典的项目
                        result['match_analysis'].pop(skill, None)
                
                # 在返回结果前添加深度类型检查
                result_user_skills = result.get('user_skills', {})
                result_job_skills = result.get('job_skills', {})
                result_match = {
                    'overall_match': result.get('overall_match', 0),
                    'match_analysis': {},  # 先设置为空字典，然后逐项验证
                    'competitiveness_analysis': result.get('competitiveness_analysis', ''),
                    'improvement_suggestions': result.get('improvement_suggestions', []),
                    'career_prospects': result.get('career_prospects', '')
                }
                
                # 确保 match_analysis 中的每一项都是合法的
                match_analysis_dict = result.get('match_analysis', {})
                if isinstance(match_analysis_dict, dict):
                    for skill, skill_data in list(match_analysis_dict.items()):
                        # 确保每个技能的数据是字典
                        if not isinstance(skill_data, dict):
                            logger.error(f"技能 {skill} 的数据不是字典: {type(skill_data)}")
                            continue
                            
                        # 确保必要的字段存在且类型正确
                        validated_skill_data = {}
                        for field in ['job_requirement', 'user_level', 'match_percentage', 'gap']:
                            value = skill_data.get(field)
                            if field in ['job_requirement', 'user_level', 'match_percentage']:
                                # 数值字段
                                if not isinstance(value, (int, float)):
                                    try:
                                        value = float(value) if value else 0
                                    except (ValueError, TypeError):
                                        value = 0
                            elif field == 'gap':
                                # 差距可以是正负数
                                if not isinstance(value, (int, float)):
                                    try:
                                        value = float(value) if value else 0
                                    except (ValueError, TypeError):
                                        value = 0
                        
                            validated_skill_data[field] = value
                        
                        # 将验证过的数据添加到结果中
                        result_match['match_analysis'][skill] = validated_skill_data
                
                # 确保user_skills和job_skills中的值都是数值类型
                for skills_dict in [result_user_skills, result_job_skills]:
                    for skill, level in list(skills_dict.items()):
                        if not isinstance(level, (int, float)):
                            try:
                                skills_dict[skill] = float(level) if level else 0
                            except (ValueError, TypeError):
                                skills_dict.pop(skill)  # 移除无效的技能
                
                # 记录最终返回的数据结构
                logger.info(f"用户技能数量: {len(result_user_skills)}, 职位技能数量: {len(result_job_skills)}, match_analysis项数: {len(result_match['match_analysis'])}")
                
                return result_user_skills, result_job_skills, result_match
                
            except json.JSONDecodeError as e:
                logger.error(f"JSON解析错误: {str(e)}, 内容: {content[:100]}...")
                return {}, {}, {}
            
        except Exception as e:
            logger.error(f"联合分析简历和职位描述出错: {str(e)}\n{traceback.format_exc()}")
            return {}, {}, {
                'overall_match': 0,
                'match_analysis': {},
                'competitiveness_analysis': '',
                'improvement_suggestions': [],
                'career_prospects': ''
            } 